
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;

namespace Rmvbediter
{
    unsafe public class BSReader : FileStream
    {
        bool isConver = false;
        public BSReader(string fileName, FileMode mode, FileAccess access, bool fileType)
            : base(fileName, mode, access)
        {
            isConver = fileType;
        }
        public T Read<T>() where T : struct
        {
            Type type = typeof(T);
            int size = Marshal.SizeOf(type);
            byte[] buf = new byte[size];
            int reader = Read(buf, 0, size);
            if (reader != size)
                throw new Exception("Not enough date");
            T ret = default(T);
            fixed (void* p = buf)
            {
                ret = (T)Marshal.PtrToStructure((IntPtr)p, type);
            }
            Console.WriteLine(object.ReferenceEquals(ret, buf));
            return ret;
        }

        public int ReadIntType(int size)
        {
            byte[] buf = new byte[size];
            Read(buf, 0, size);
            Array.Reverse(buf, 0, buf.Length);
            fixed (byte* p = buf)
            {
                return (int)*p;
            }
        }

        public object Read(Type type)
        {
            int size = Marshal.SizeOf(type);
            byte[] buf = new byte[size];
            int reader = Read(buf, 0, size);
            if (reader != size)
                throw new Exception("Not enough date");
            object ret = null;
            fixed (void* p = buf)
            {
                ret = (object)Marshal.PtrToStructure((IntPtr)p, type);
            }
            if (isConver)
            {
                Conver(type, ret);
            }
            Console.WriteLine(object.ReferenceEquals(ret, buf));
            return ret;
        }
        Dictionary<Type, List<changeType>> typeMap = new Dictionary<Type, List<changeType>>();
        class changeType
        {
            public changeType(FieldInfo f, int s)
            {
                field = f;
                size = s;
            }
            public FieldInfo field;
            public int size = 2;
        }
        List<changeType> GetFiledList(Type type)
        {
            List<changeType> ret = null;
            if (typeMap.TryGetValue(type, out ret))
                return ret;
            ret = new List<changeType>();
            foreach (FieldInfo t in type.GetFields())
            {
                Type vt = t.FieldType;
                if (vt == typeof(Int16))
                    ret.Add(new changeType(t, 2 ));
                else if (vt == typeof(Int32))
                    ret.Add(new changeType(t, 4));
                else if (vt == typeof(Int64))
                    ret.Add(new changeType(t, 8));
            }
            typeMap.Add(type, ret);
            return ret;
        }
        public object Conver(Type type, object o)
        {
            List<changeType> fileds = GetFiledList(type);
            byte[] buf = new byte[8];
            foreach (changeType f in fileds)
            {
                object value = f.field.GetValue(o);
                switch (f.size)
                {
                    case 2:
                        fixed (byte* p = buf)
                        {
                            *((Int16*)p) = (Int16)value;
                        }
                        break;
                    case 4:
                        fixed (byte* p = buf)
                        {
                            *((Int32*)p) = (Int32)value;
                        }
                        break;
                    case 8:
                        fixed (byte* p = buf)
                        {
                            *((Int64*)p) = (Int64)value;
                        }
                        break;
                    default:
                        break;
                }
                for (int i = 0; i < f.size / 2; i++)
                {
                    byte t = buf[i];
                    buf[i] = buf[f.size - i - 1];
                    buf[f.size - i - 1] = t;
                }
                switch (f.size)
                {
                    case 2:
                        fixed (byte* p = buf)
                        {
                            value = *(Int16*)p;
                        }
                        break;
                    case 4:
                        fixed (byte* p = buf)
                        {
                            value = *(Int32*)p;
                        }
                        break;
                    case 8:
                        fixed (byte* p = buf)
                        {
                            value = *(Int64*)p;
                        }
                        break;
                }
                f.field.SetValue(o, value);
            }
            return o;
        }
        //public void Conver(byte o, int size)
        //{
        //    //byte []buf = new byte[size];
        //    //for (int i = 0; i < size; i++)
        //    //{
        //    //    buf[i] = (byte)(o >> (size - i) * 8);
        //    //}
        //    fixed (byte* p = &o)
        //    {
        //    }
        //}
    }
}
